I always thought that I was doing my unit testing, programming and refactoring in small steps. But during the last year or so I learned that I was wrong. Dead wrong.
I have been interested in code quality and craftsmanship for some time now. The books I read and the people I talked to gave me the first hints that I should do my work in smaller steps. Then, at SoCraTes Conference 2012, I learned about the Taking Baby Steps exercise by Adrian Bolboaca. This showed me how small your steps could really be.
I still don’t use the “Baby Steps” technique in my projects - I only use it as an exercise. But since I learned about it, I am trying to take smaller and smaller steps in my projects too.
An example would be handy right now
Today I was refactoring some code I wrote earlier. I had a class that did two things, and I wanted to pull some methods out into a new class. Then both classes would only do one thing and better adhere to the Single Responsibility Principle.
I have simplified the example a little bit. Anyway, the code was something like this:
public class FooService {
public List listAll() {
...
}
public List listBy(Name name) {
...
}
//Other methods that have a different responsibility
}
</pre>
Step 1: Create a new class FooLists and make it accessible through FooService
public class FooService {
public FooLists lists() {
return fooLists;
}
public List listAll() {
...
}
public List listBy(Name name) {
...
}
//Other methods that have a different responsibility
}
</pre>
All tests are still green. Of course they are: I only added a new method.
Commit.
Step 2: Copy the two list... methods to FooLists.
All tests are still green. Of course, I only added new methods in a class that is not used yet.
Commit.
Step 3: Change listAll so it delegates to FooLists:
public class FooService {
public FooLists lists() {
return fooLists;
}
public List listAll() {
return fooLists.listAll();
}</strong>
public List listBy(Name name) {
...
}
//Other methods that have a different responsibility
}
</pre>
This was the first "real" change. All tests are still green. Phew.
Commit.
Step 4: Find all references of listAll(). Change the first to lists().listAll()
Run all the tests. They are still green.
Commit.
Step 5: Change all other references of listAll()
Run all the tests. They are still green.
Commit.
Step 6: Remove the method listAll() from FooService
Run all the tests. They are still green.
Commit.
Steps 7-n: Do the same for listBy(name). Run the tests after each step.
This was easy
This was really easy. I never had the feeling that I am on thin ice. I always could run "hg revert && hg purge" and only lose the work of a couple of minutes.
I am not yet sure if the end result is what I want. It is definitely better than before. But now there is this train wreck code like "fooService.lists().listAll()" in other parts of the system.
I think I know what I'll do next ;)
You might also be interested in...
- Software Quality for Developers Learn about software quality, TDD, ... in this 6-part video course.
- Simplicity: Simplify. Then simplify more. And: Don't let the code become complicated in the first place.
- Developers testing their own code Some considerations about testing code
- It's about courage: About refactoring, and courage as an agile value in general
- Learn more about how I can help you save money and earn money by improving your agile software development process.